<?php

  class DateTimeParser extends Base {

    /** @var integer The timestamp to work with. */
    private $timestamp = 0;

    /** @var integer The year to work with. */
    private $year = 0;

    /** @var integer The month to work with. */
    private $month = 0;

    /** @var integer The day to work with. */
    private $day = 0;

    /** @var integer The hour to work with. */
    private $hour = 0;

    /** @var integer The minute to work with. */
    private $minute = 0;

    /** @var integer The second to work with. */
    private $second = 0;

    /** @var array This is an associative array for english days. */
    public static $days = array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday");

    /** @var array This is an associative array for english months. */
    public static $months = array("January", "Febrary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December");

    /**
     * Store and save parameters in private privateiables for further use.
     *
     * @param integer $year The number of the year, may be a two or four digit value,
     * with values between 0-69 mapping to 2000-2069 and 70-100 to 1970-2000.
     * On systems where time_t is a 32bit signed integer, as most common today,
     * the valid range for year  is somewhere between 1901 and 2038. However,
     * before PHP 5.1.0 this range was limited from 1970 to 2038 on some systems
     * (e.g. Windows).
     *
     * @param integer $month The number of the month.
     * @param integer $day The number of the day.
     * @param integer $hour The number of the hour.
     * @param integer $minute The number of the minute.
     * @param integer $second The number of seconds past the minute.
     */
    public function __construct(Integer $year = null, Integer $month = null, Integer $day = null, Integer $hour = null, Integer $minute = null, Integer $second = null) {
      $this->year = $year == null ? 0 : $year->integerValue();
      $this->month = $month == null ? 0 : $month->integerValue();
      $this->day = $day == null ? 0 : $day->integerValue();
      $this->hour = $hour == null ? 0 : $hour->integerValue();
      $this->minute = $minute == null ? 0 : $minute->integerValue();
      $this->second = $second == null ? 0 : $second->integerValue();
      $this->rebuildTimeStamp();
    }

    /**
     * The Unix timestamp of the private arguments given.
     * If the private arguments are invalid, the function returns FALSE (before PHP 5.1 it returned -1).
     *
     * @return integer The complete timestamp as a mixed variable.
     */
    public function getTimestamp() {
      return $this->timestamp;
    }

    /**
     * Return the year of the timestamp.
     * @return Integer The year as an integer.
     */
    public function getYear() {
      return new Integer($this->year);
    }

    /**
     * Return the month of the timestamp.
     * @return Integer The month.
     */
    public function getMonth() {
      return new Integer($this->month);
    }

    /**
     * Return the day of the timestamp.
     * @return Integer The day.
     */
    public function getDay() {
      return new Integer($this->day);
    }

    /**
     * Return the hour of the timestamp.<br />
     * @return Integer The hour as an integer.
     */
    public function getHour() {
      return new Integer($this->hour);
    }

    /**
     * Return the minute of the timestamp.<br />
     * @return Integer The minute as an integer.
     */
    public function getMinute() {
      return new Integer($this->minute);
    }

    /**
     * Return the second of the timestamp.<br />
     * @return Integer The second as an integer.
     */
    public function getSecond() {
      return new Integer($this->second);
    }

    /**
     *
     * @param IInteger $start
     * @param IInteger $stop
     * @return ArrayList $al
     */
    public static function getRangeOfYears(IInteger $start, IInteger $stop) {
      $ar = array();

      for ($i = (date("Y") - $start->integerValue()); $i <= (date("Y") + $stop->integerValue()); ++$i) {
        array_push($ar, new Integer($i));
      }
      return new ArrayList($ar);
    }

    /**
     * Set the value for the complete timestamp.<br />
     *
     * @param insteger $value The complete timestamp, built with MakeTime().
     *
     * @exception UnexpectedResult If the value is set before an Add Method, the
     * timestamp will not work properly because the _Rebuild() method is never
     * called after this method.<br />
     *
     * @see MakeTime()
     * @see Rebuild()
     */
    public function setTimestamp($value) {
      $this->timestamp = $value;
      $this->rebuildDatas();
    }

    /**
     * Add days to the timestamp.
     * @param IInteger $value The day to add. If the value is negative, days will be subbed.
     */
    public function addDay(IInteger $value) {
      $this->timestamp += (60 * 60 * 24 * $value->integerValue());
      $this->rebuildDatas();

      return $this;
    }

    /**
     * Add months to the timestamp.<br />
     *
     * @param Integer $value The month to add. If the value is negative, months will be
     * substracted.
     *
     * @see _Rebuild()
     */
    public function addMonth(Integer $value) {
      $nbdays = 0;

      if ($value->integerValue() > 0) {
        for ($i = 0; $i < $value->integerValue(); ++$i)
          $nbdays += date("t", mktime(0, 0, 0, $this->month + $i, 1, $this->year));
      } elseif ($value->integerValue() < 0) {
        for ($i = $value->integerValue(); $i < 0; $i++)
          $nbdays -= date("t", mktime(0, 0, 0, $this->month + $i, 1, $this->year));
      }

      $this->timestamp += ((60 * 60 * 24) * $nbdays);
      $this->rebuildDatas();

      return $this;
    }

    /**
     * Add years to the timestamp.
     *
     * @param Integer $value The year to add. If the value is negative, years will be subbed.
     * @link http://be2.php.net/manual/en/function.mktime.php
     */
    public function addYear(Integer $value) {
      if ($value->integerValue() > 0) {
        for ($i = 0; $i < $value->integerValue(); ++$i) {
          if (date("L", mktime(0, 0, 0, 1, 1, $this->year + $i)) == 1) {
            $this->timestamp += (60 * 60 * 24 * 366);
          } else {
            $this->timestamp += (60 * 60 * 24 * 365);
          }
        }
      } elseif ($value->integerValue() < 0) {
        for ($i = $value->integerValue(); $i < 0; $i++) {
          if (date("L", mktime(0, 0, 0, 1, 1, $this->year - $i)) == 1) {
            $this->timestamp -= (60 * 60 * 24 * 366);
          } else {
            $this->timestamp -= (60 * 60 * 24 * 365);
          }
        }
      }
      $this->rebuildDatas();

      return $this;
    }

    /**
     * Add hours to the timestamp.<br />
     *
     * @param integer $value The hour to add. If the value is negative, hours will be
     * substracted.
     *
     * @see _Rebuild()
     */
    public function addHour(Integer $value) {
      $this->timestamp += (60 * 60 * $value->integerValue());
      $this->rebuildDatas();

      return $this;
    }

    /**
     * Add minutes to the timestamp.<br />
     *
     * @param integer $value The minute to add. If the value is negative, minutes will
     * be substracted.
     *
     * @see _Rebuild()
     */
    public function addMinute(Integer $value) {
      $this->timestamp += (60 * $value->integerValue());
      $this->rebuildDatas();

      return $this;
    }

    /**
     * Add seconds to the timestamp.<br />
     *
     * @param integer $value The second to add. If the value is negative, secondss will
     * be substracted.
     *
     * @see _Rebuild()
     */
    public function addSecond(Integer $value) {
      $this->timestamp += $value->integerValue();
      $this->rebuildDatas();

      return $this;
    }

    /**
     * Format a local time / date.
     * Returns a string formatted according to the given format char using the timestamp.
     * @param Char $format The format.
     * @return String Returns a formatted date string.
     * @link http://fr.php.net/manual/en/function.date.php
     */
    public function format(String $format) {
      return new String(date($format->toString(), $this->timestamp));
    }

    /**
     * Build the Unix timestamp corresponding to the arguments given. This
     * timestamp is a long integer containing the number of seconds between the
     * Unix Epoch (January 1 1970 00:00:00 GMT) and the time specified.<br />
     *
     * @param integer $year The number of the year, may be a two or four digit value,
     * with values between 0-69 mapping to 2000-2069 and 70-100 to 1970-2000.
     * On systems where time_t is a 32bit signed integer, as most common today,
     * the valid range for year  is somewhere between 1901 and 2038. However,
     * before PHP 5.1.0 this range was limited from 1970 to 2038 on some systems
     * (e.g. Windows).
     *
     * @param integer $month The number of the month.
     *
     * @param integer $day The number of the day.
     *
     * @param integer $hour The number of the hour.
     *
     * @param integer $minute The number of the minute.
     *
     * @param integer $second The number of seconds past the minute.
     *
     * @return timestamp The Unix timestamp of the arguments given. If the arguments are
     * invalid, the function returns FALSE (before PHP 5.1 it returned -1).<br /><br />
     *
     * @link http://be2.php.net/manual/en/function.mktime.php
     */
    public static function makeTime(Integer $year = null, Integer $month = null, Integer $day = null, Integer $hour = null, Integer $minute = null, Integer $second = null) {
      return mktime($hour == null ? 0 : $hour->integerValue(), $minute == null ? 0 : $minute->integerValue(), $second == null ? 0 : $second->integerValue(), $month == null ? 0 : $month->integerValue(), $day == null ? 0 : $day->integerValue(), $year == null ? 0 : $year->integerValue());
    }

    /**
     * Convert the date to a short string as '01/01/1900'.<br />
     *
     * @param Char $separator The separator to use in the string.
     * Default value is a slash.
     *
     * @return String The date.
     */
    public function toShortDateString(Char $separator = null) {
      if ($separator == null) {
        return new String(substr("0" . $this->day, -2) . "/" . substr("0" . $this->month, -2) . "/" . $this->year);
      } else {
        return new String(substr("0" . $this->day, -2) . $separator->charValue() . substr("0" . $this->month, -2) . $separator->charValue() . $this->year);
      }
    }

    /**
     * Convert the date to a long string as 'monday 1 January 1900'.<br />
     *
     * @return String The long date.
     */
    public function toLongDateString() {
      return new String($this->format(new String("l"))->toString() . " " . $this->day . " " . self::$months[$this->month - 1] . " " . $this->year);
    }

    /**
     * Convert the time to a short string as '12:00'.
     * @param Char $separator The separator to use in the string. Default value is ':'.
     * @return String The time.
     */
    public function toShortTimeString(Char $separator = null) {
      if ($separator == null) {
        return new String(substr("0" . $this->hour, -2) . ":" . substr("0" . $this->minute, -2));
      } else {
        return new String(substr("0" . $this->hour, -2) . $separator->charValue() . substr("0" . $this->minute, -2));
      }
    }

    /**
     * The time with hour, minutes and seconds.
     * @param Char $separator The separator.
     * @return String The time as hh:mm:ss.
     */
    public function toLongTimeString(Char $separator = null) {
      if ($separator == null) {
        return new String(substr("0" . $this->hour, -2) . ":" . substr("0" . $this->minute, -2) . ":" . substr("0" . $this->second, -2));
      } else {
        return new String(substr("0" . $this->hour, -2) . $separator->charValue() . substr("0" . $this->minute, -2) . $separator->charValue() . substr("0" . $this->second, -2));
      }
    }

    /**
     * Return the time in a long string format like 'd months Year H:i:s'.<br />
     *
     * @param Char $separator the character to seperate values.
     *
     * @return String The time in a long string format.
     */
    public function toLongString(Char $separator = null) {
      return new String($this->toLongDateString()->toString() . " " . $this->toLongTimeString($separator)->toString());
    }

    /**
     * Convert the date and time to a short string as '01/01/1900 12:00:00'.<br />
     *
     * @param Char $date_separator The separator to use for the date. Default value
     * is '/'.
     *
     * @param Char $time_separator The separator to use for the time.
     * Defaulkt value is ':'.
     *
     * @return String The date and time.
     */
    public function toShortString(Char $dateSeparator = null, Char $timeSeparator = null) {
      return new String($this->toShortDateString($dateSeparator) . " " . $this->toShortTimeString($timeSeparator));
    }

    /**
     * Rebuild all private privateiables for getters.<br />
     * This method is called every time a method is applied on the timestamp.
     *
     * @see <a href="http://be2.php.net/manual/en/function.getdate.php">getdate()</a>
     */
    private function rebuildDatas() {
      $data = getdate($this->timestamp);

      $this->year = $data['year'];
      $this->month = $data['mon'];
      $this->day = $data['mday'];
      $this->hour = $data['hours'];
      $this->minute = $data['minutes'];
      $this->second = $data['seconds'];
    }

    /** Rebuild the timestamp according to all private variables. */
    private function rebuildTimeStamp() {
      $this->timestamp = mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
    }

    /**
     * @param int $year
     * @deprecated
     */
    public function setYear($year) {
      $this->year = $year;
      BeObject::$LOG->warn("Method is deprecated.");
    }

    /**
     * @param int $month
     * @deprecated
     */
    public function setMonth($month) {
      $this->month = $month;
      BeObject::$LOG->warn("Method is deprecated.");
    }

    /**
     * @param int $day
     * @deprecated
     */
    public function setDay($day) {
      $this->day = $day;
      BeObject::$LOG->warn("Method is deprecated.");
    }

    /**
     * @param int $hour
     * @deprecated
     */
    public function setHour($hour) {
      $this->hour = $hour;
      BeObject::$LOG->warn("Method is deprecated.");
    }

    /**
     * @param int $minute
     * @deprecated
     */
    public function setMinute($minute) {
      $this->minute = $minute;
      BeObject::$LOG->warn("Method is deprecated.");
    }

    /**
     * @param int $second
     * @deprecated
     */
    public function setSecond($second) {
      $this->second = $second;
      BeObject::$LOG->warn("Method is deprecated.");
    }

  }

?>
